#!/usr/bin/env python3

import sys

import yaml


def escape(s):
    return str(s) \
        .replace('<', '\<') \
        .replace('>', '\>') \
        .replace('|', '\|') \
        .replace('\r\n', '<br>') \
        .replace('\r', '<br>') \
        .replace('\n', '<br>')


def bold(s):
    return '**' + str(s) + '**'


def get(dic, key):
    if key in dic:
        value = dic[key]

        if type(value) == list:
            rows = ''
            row_id = 1
            for row in value:
                rows += str(row_id) + '. ' + escape(row) + '<br>'
                row_id += 1
            return rows

        if type(value) == dict:
            rows = ''
            for row_key, row_value in sorted(value.items()):
                rows += escape(row_key) + ': ' + escape(row_value) + '<br>'
            return rows

        return escape(value)
    else:
        return ''


def update_markdown():
    sys.stdout = open("job-exit-spec.md", "w")
    with open('job-exit-spec.yaml', 'r') as stream:
        data = yaml.safe_load(stream)

    schema = data['schema']
    spec = data['spec']

    print('# PAI Job Exit Spec')
    print('1. See details in [job-exit-spec.yaml](job-exit-spec.yaml)')
    print('2. This markdown file is generated by [update_markdown.py](update_markdown.py) with [job-exit-spec.yaml](job-exit-spec.yaml)')
    print('3. See full doc in [PAI Job Exit Spec User Manual](user-manual.md)')
    print('')

    print('## Spec Schema')
    print('|field|description|required|unique|type|range|')
    print('|-----|-----------|--------|------|----|----|')
    for field in schema:
        print('|', bold(get(field, 'field')), '|',
              get(field, 'description'), '|',
              get(field, 'required'), '|',
              get(field, 'unique'), '|',
              get(field, 'type'), '|',
              get(field, 'range'), '|')
    print('')

    print('## Spec Table')
    print('1. You may need to **scroll right side to see full table**.')
    print('2. The code **256** is just used to represent all **undefined '
          'positive** exitcodes in this spec, and the specific undefined exitcode '
          'will always override it to expose to user.')
    print('3. The code **-8000** is just used to represent all **undefined '
          'negative** exitcodes in this spec, and the specific undefined exitcode '
          'will always override it to expose to user.')
    print('')
    print('|code|phrase|issuer|causer|type|stage|behavior|reaction|reason|repro|solution|pattern|')
    print('|----|------|------|------|----|-----|--------|--------|------|-----|--------|-------|')
    for code in spec:
        print('|', bold(get(code, 'code')), '|',
              bold(get(code, 'phrase')), '|',
              get(code, 'issuer'), '|',
              get(code, 'causer'), '|',
              get(code, 'type'), '|',
              get(code, 'stage'), '|',
              get(code, 'behavior'), '|',
              get(code, 'reaction'), '|',
              get(code, 'reason'), '|',
              get(code, 'repro'), '|',
              get(code, 'solution'), '|',
              get(code, 'pattern'), '|')
    print('')


def main():
    update_markdown()


if __name__ == "__main__":
    main()
